/*-------------------------------------------------------------------------
 *
 * pqexpbuffer.h
 *	  "PQExpBuffer" 函数的声明/定义。
 *
 * PQExpBuffer 提供了一种无限扩展的字符串数据类型。
 * 它可以用于缓冲普通的 C 字符串（以 null 结尾的文本）或任意二进制数据。所有存储都是使用 malloc() 分配的。
 *
 * 此模块本质上与后端的 StringInfo 数据类型相同，但它旨在用于前端 libpq 和客户端应用程序。
 * 因此，它不依赖于 palloc() 或 elog()。
 *
 * 它依赖于 vsnprintf(); 如果配置找到 libc 不提供可用的 vsnprintf()，则会将我们自己的实现的副本链接到 libpq 中。
 *
 * Portions Copyright (c) 1996-2022, PostgreSQL Global Development Group
 * Portions Copyright (c) 1994, Regents of the University of California
 *
 * src/interfaces/libpq/pqexpbuffer.h
 *
 *-------------------------------------------------------------------------
 */
#ifndef PQEXPBUFFER_H
#define PQEXPBUFFER_H

/*-------------------------
 * PQExpBufferData保存可扩展字符串的信息。
 *		data 是字符串的当前缓冲区（使用 malloc 分配）。
 *		len  是当前字符串的长度。保证在 data[len] 处有一个结束符 '\0'，尽管当字符串保存二进制数据而不是文本时，这并没有什么用。
 *		maxlen 是 'data' 的分配字节大小，即我们当前可以存储在 'data' 中的最大字符串大小（包括结束符 '\0' 字符），而无需重新分配更多空间。我们必须始终确保 maxlen > len。
 *
 * 如果我们未能为字符串缓冲区分配足够的内存，则会发生异常。在这种情况下，data 指向一个静态分配的空字符串，len = maxlen = 0。
 *-------------------------
 */
typedef struct PQExpBufferData
{
	char	   *data;
	size_t		len;
	size_t		maxlen;
} PQExpBufferData;

typedef PQExpBufferData *PQExpBuffer;

/*------------------------
 * 测试一个损坏的（内存不足）PQExpBuffer。
 * 当一个缓冲区“损坏”时，除重置或删除它之外的所有操作都是无操作。
 *------------------------
 */
#define PQExpBufferBroken(str)	\
	((str) == NULL || (str)->maxlen == 0)

/*------------------------
 * 相同，但用于使用静态或局部 PQExpBufferData 结构时。
 * 对于这种情况，空指针测试是无用的，可能会引发编译器警告。
 *------------------------
 */
#define PQExpBufferDataBroken(buf)	\
	((buf).maxlen == 0)

/*------------------------
 * PQExpBuffer 中数据缓冲区的初始大小。
 * 注意：这必须足够大以容纳可能由 PQrequestCancel() 返回的错误消息。
 *------------------------
 */
#define INITIAL_EXPBUFFER_SIZE	256

/*------------------------
 * 创建 PQExpBuffer 对象有两种初始方法：
 *
 * PQExpBuffer stringptr = createPQExpBuffer();
 *		PQExpBufferData 和数据缓冲区都使用 malloc 分配。
 *
 * PQExpBufferData string;
 * initPQExpBuffer(&string);
 *		数据缓冲区使用 malloc 分配，但 PQExpBufferData 是预先提供的。
 *		如果 PQExpBufferData 是另一个结构的字段，这种方法是合适的。
 *-------------------------
 */

/*------------------------
 * createPQExpBuffer
 * 创建一个空的 'PQExpBufferData' 并返回指向它的指针。
 */
extern PQExpBuffer createPQExpBuffer(void);

/*------------------------
 * initPQExpBuffer
 * 初始化一个 PQExpBufferData 结构（内容之前未定义），以描述一个空字符串。
 */
extern void initPQExpBuffer(PQExpBuffer str);

/*------------------------
 * 要销毁 PQExpBuffer，可以使用以下任一方法：
 *
 * destroyPQExpBuffer(str);
 *		free() 两个数据缓冲区和 PQExpBufferData。
 *		这是 createPQExpBuffer() 的逆操作。
 *
 * termPQExpBuffer(str)
 *		free() 数据缓冲区，但不释放 PQExpBufferData 本身。
 *		这是 initPQExpBuffer() 的逆操作。
 *
 * 注意：某些例程使用 PQExpBuffer 构建字符串，然后释放 PQExpBufferData，但将数据字符串本身返回给调用者。此时数据字符串看起来像一个普通的 malloc 分配的字符串。
 */
extern void destroyPQExpBuffer(PQExpBuffer str);
extern void termPQExpBuffer(PQExpBuffer str);

/*------------------------
 * resetPQExpBuffer
 *		将 PQExpBuffer 重置为空
 *
 * 注意：如果可能，“损坏”的 PQExpBuffer 会恢复正常。
 */
extern void resetPQExpBuffer(PQExpBuffer str);

/*------------------------
 * enlargePQExpBuffer
 * 确保在缓冲区中有足够的空间以容纳“needed”更多字节
 * （“needed”不包括终止空字符）。
 *
 * 如果成功返回1，如果无法扩大缓冲区则返回0。 （在后者情况下
 * 缓冲区将处于“损坏”状态。）
 */
extern int	enlargePQExpBuffer(PQExpBuffer str, size_t needed);

/*------------------------
 * printfPQExpBuffer
 * 在fmt（类似sprintf的格式字符串）的控制下格式化文本数据
 * 并将其插入到str中。如果必要，将为str分配更多空间。
 * 这是一个便利程序，它执行与
 * resetPQExpBuffer()后跟appendPQExpBuffer()相同的操作。
 */
extern void printfPQExpBuffer(PQExpBuffer str, const char *fmt,...) pg_attribute_printf(2, 3);

/*------------------------
 * appendPQExpBuffer
 * 在fmt（类似sprintf的格式字符串）的控制下格式化文本数据
 * 并将其附加到str中已有的内容上。如果必要，将为str分配更多空间。
 * 这有点像sprintf和
 * strcat的组合。
 */
extern void appendPQExpBuffer(PQExpBuffer str, const char *fmt,...) pg_attribute_printf(2, 3);

/*------------------------
 * appendPQExpBufferStr
 * 将给定字符串附加到PQExpBuffer，如果必要则分配更多空间。
 */
extern void appendPQExpBufferStr(PQExpBuffer str, const char *data);

/*------------------------
 * appendPQExpBufferChar
 * 将一个字节附加到str中。
 * 类似于appendPQExpBuffer(str, "%c", ch)，但速度更快。
 */
extern void appendPQExpBufferChar(PQExpBuffer str, char ch);

/*------------------------
 * appendBinaryPQExpBuffer
 * 将任意二进制数据附加到PQExpBuffer，如果必要则分配更多空间。
 */
extern void appendBinaryPQExpBuffer(PQExpBuffer str,
									const char *data, size_t datalen);

#endif							/* PQEXPBUFFER_H */
